package com.example.kotlindemo.genericity

import android.widget.Button
import android.widget.TextView
import com.example.kotlindemo.constructorstudy.Food
import com.example.kotlindemo.constructorstudy.Fruits2

class GenericitySample {


    /**
     *   Kt中的泛型
     *     - 使用关键字 out 来支持协变，等同于Java中的上界通配符 ? extends
     *     - 使用 in 来支持逆变，等同于下界通配符 Java ? super
     *
     *
     */

    //上界 ，协变
    var tvList1 :List<out TextView> = ArrayList<Button>()

    var tvList2: List<out Fruits2> ?=null



//    = ArrayList<TextView>()




//1. Java 举例
    /**
     * 1.  List<Button> buttons = new ArrayList<Button>();
     *     List<? extends TextView> textViews = buttons;
     *
     *     ? extends 叫做 【上界通配符】 ，extends 限制了泛型类型的父类型
     *         1. ?是个通配符，表示这个List的泛型类型是一个未知类型
     *         2. extends 限制了这个未知类型的上界，也就是泛型必须瞒住这个extends的限制条件
     *           这里的extends与class的extends有点区别
     *               1.它的范围不仅包含子类，还包含本身，也就是TextView
     *               2.它还有implements的意思，即这里的上界也可以是interface
     *  2. 这样使用 List<?> 其实是 List<? extends Object> 的缩写。
     * 说明【生产者】：get的时候，可以保证是最顶级的类型（多态），但是add的时候，如果
     * 未知类型是子类型，你放的是顶级类型，就不可以了（当然，顶级放顶级是可以的），
     * 所以编译器就没法确定? 的类型，所以不能add
     *
     *     List<? extends TextView> textViews = new ArrayList<Button>();
     *    TextView textView = textViews.get(0); // 👈 get 可以
     *     textViews.add(textView);
    //             👆 add 会报错，no suitable method found for add(TextView)

     *
     * 总结：使用 ? extends 泛型通配符的List，只能够向外提供数据被消费，这个角度讲
     * ，向外提供数据的一方称为【生产者Producer】 ，与之对应的另一个概念叫做【Consumer】，
     * 对应的泛型 ? Super
     *
     *
     *
     */

}

    /**
     * 2.  List<? super Button> buttons = new ArrayList<TextView>();
     *     ? super 叫做【下界通配符】，可以使用Java泛型具有的【逆变性】
     *        1.通配符 ? 表示List泛型类型是一个未知类型
     *        2.super限制了这个未知类型的下界，也就是泛型必须满足super的限制条件
     *           super表示不仅包含Button的直接和间接父类，同样包含Button本身
     *           super同样支持interface
     *
     */
















































